<template>
    <div class="workflow-container">
        <div class="workflow-zoom" :class="{'close':collapse}">
            <div class="zoom-btn" @click="changeZoom(-10)">
                <i class="el-icon-minus"/>
            </div>
            <div class="current-zoom">{{ zoom }}%</div>
            <div class="zoom-btn" @click="changeZoom(10)">
                <i class="el-icon-plus"/>
            </div>
        </div>
        <div class="workflow-operation-btn-container">
            <el-button class="workflow-operation-btn" plain @click="dialogVisible = true">
                {{ $i18n.t('button.baseInfo') }}
            </el-button>
            
            <el-button class="workflow-operation-btn" plain @click="noticeSettingState = true">
                {{ $i18n.t('button.noticeConfig') }}
            </el-button>
            <el-button class="workflow-operation-btn" type="primary" @click="onSave">
                {{ $i18n.t('button.save') }}
            </el-button>
        </div>
        
        <div class="workflow-content" :style="`transform: scale(${zoom/100}); transform-origin: 50% 0px 0px;`">
            <div class="node-container">
                <div class="start-container" v-if="nodeInfo">
                    <div class="start-node">{{ $i18n.t('label.start') }}</div>
                </div>
                <node-context v-model="nodeInfo"
                              :active-id="activeId"/>
                <div class="end-node" v-if="nodeInfo">
                    <div class="end-node-point"></div>
                    <div class="end-node-text">{{ $i18n.t('label.flowEnd') }}</div>
                </div>
                <!--条件操作抽屉-->
                <condition-drawer :show-condition="showCondition"
                                  :condition-node="currentCondition"
                                  @on-close="showCondition=false"
                                  @on-save="onSaveCondition"/>
                <!--节点操作抽屉-->
                <node-opera-drawer :show-node-opera="nodeOperaState"
                                   :node-info="currentNodeInfo"
                                   @on-save="onSaveNodeInfo"
                                   @on-close="nodeOperaState = false"/>
            </div>
        </div>
        
        <workflow-info :dialog-visible="dialogVisible"
                       :workflow-data="workflowData"
                       :edit-flag="true"
                       @on-close="dialogVisible = false"
                       @on-save="saveBaseInfo"/>
        
        
        <notice-setting-drawer :show-sate="noticeSettingState"
                               :workflow-data="workflowData"
                               @on-save="onSaveNoticeConfig"
                               @on-close="noticeSettingState = false"></notice-setting-drawer>
    </div>
</template>

<script lang="ts">
import {EventTypeEnum, NodeTypeEnum, ZoomEnum} from "./enums/node.enum";
import WorkflowService from "./service/workflow.service";
import WorkflowModel from "./model/workflow.model";
import Utils from "@/utils/utils";
import TreeUtil from "./util/tree-util";
import ResponseModel from "@/common/model/response.model";
import NodeModel from "./model/node.model";
import ConditionDrawer from "./condition-drawer/condition-drawer.vue";
import {Component, Prop, Vue, Watch} from "vue-property-decorator";
import NodeContext from './node-context/node-context.vue'
import NodeOperaDrawer from './node-opera-drawer/node-opera-drawer.vue';
import {SettingsGetterEnum} from "@/store/enum/store.enum";
import {ResponseStatusEnum} from "@/common/enum/common.enum";
import WorkflowInfo from './workflow-info/workflow-info.vue';
import NoticeSettingDrawer from './notice-setting-drawer/notice-setting-drawer.vue';

@Component({components: {ConditionDrawer, NodeContext, NodeOperaDrawer, WorkflowInfo, NoticeSettingDrawer}})
export default class Workflow extends Vue {
    
    /**
     * 流程id
     */
    @Prop()
    public id: string;
    /**
     * 方法缩小倍数
     */
    private zoom: number = ZoomEnum.default;
    /**
     * 提交数据
     */
    private workflowData: WorkflowModel = new WorkflowModel(Utils.uuid());
    /**
     * 模态框状态
     */
    private dialogVisible = false;
    /**
     * 树信息
     **/
    private nodeInfo: NodeModel = new NodeModel();
    /**
     * 激活节点
     */
    private activeId = '';
    /**
     * 条件抽屉状态
     */
    private showCondition = false;
    /**
     * 当前条件节点
     */
    private currentCondition: NodeModel = new NodeModel();
    /**
     * 节点操作抽屉状态
     */
    private nodeOperaState = false;
    /**
     * 当前选择操作节点信息
     */
    private currentNodeInfo: NodeModel = new NodeModel();
    
    /**
     * 通知设置抽屉开关
     */
    private noticeSettingState = false;
    
    private changeZoom(value: number): void {
        this.zoom = this.zoom + value;
        if (this.zoom < ZoomEnum.min) {
            this.zoom = ZoomEnum.min;
        } else if (this.zoom > ZoomEnum.max) {
            this.zoom = ZoomEnum.max;
        }
    }
    
    @Watch('nodeInfo', {immediate: true, deep: true})
    private nodeInfoChange(newVal: NodeModel, oldVal: NodeModel) {
        this.nodeInfo = newVal;
    }
    
    /**
     * 保存工作流
     */
    private onSave() {
        TreeUtil.dataTransfer(this.nodeInfo, this.workflowData);
        WorkflowService.saveWorkflow(this.workflowData).then((res: ResponseModel) => {
            if (res.status === ResponseStatusEnum.success) {
                this.$message.success('保存成功');
            }
        });
    }
    
    private beforeMount() {
        this.getWorkflowData();
    }
    
    private saveBaseInfo(data: WorkflowModel) {
        this.workflowData = data;
        this.dialogVisible = false;
    }
    
    private getWorkflowData() {
        if (!_.isEmpty(this.id)) {
            WorkflowService.getWorkflow(this.id).then((res: ResponseModel<WorkflowModel>) => {
                if (res.status === ResponseStatusEnum.success) {
                    this.workflowData = res.data;
                    const nodeTree = TreeUtil.createNodeByWorkflowData(res.data);
                    this.$nextTick(() => {
                        this.nodeInfo = nodeTree;
                        this.activeId = nodeTree.nodeId;
                    })
                }
            })
        } else {
            this.initData();
        }
        
    }
    
    private mounted() {
        // 点击切换选中
        this.$bus.$on(EventTypeEnum.clickNode, (data: { nodeId: string, type: NodeTypeEnum }) => {
            this.clickNode(data.nodeId, data.type);
        });
        
        // 删除
        this.$bus.$on(EventTypeEnum.deleteNode, (nodeId: string): void => {
            this.deleteNode(nodeId);
        });
        
        // 新增
        this.$bus.$on(EventTypeEnum.addNode, ({type, nodeId}): void => {
            this.onAddNode(type, nodeId);
        });
    }
    
    private beforeDestroy() {
        this.$bus.$off(Object.values(EventTypeEnum as {}) as string[]);
    }
    
    /**
     * 删除节点
     */
    private deleteNode(nodeId: string) {
        const closeNode = TreeUtil.findParentNodeById(this.nodeInfo, nodeId);
        if (!_.isEmpty(closeNode.child.child)) {
            closeNode.child = closeNode.child.child;
            closeNode.child.pNodeId = closeNode.nodeId;
        } else {
            delete closeNode.child;
        }
        this.activeId = this.activeId === "" ? closeNode.nodeId : this.nodeInfo.nodeId;
    }
    
    /**
     * 新增节点
     * @param type
     * @param nodeId
     */
    private onAddNode(type: NodeTypeEnum, nodeId: string) {
        const currentNode = TreeUtil.findNodeByProperties(this.nodeInfo, nodeId);
        const tempNode: NodeModel = new NodeModel();
        tempNode.nodeId = TreeUtil.getTreeId();
        if (type === NodeTypeEnum.condition) {
            const condition = [
                {
                    title: 'label.condition',
                    name: 'label.conditionTip',
                    child: currentNode.child,
                    nodeId: TreeUtil.getTreeId(),
                    type: NodeTypeEnum.conditionItem,
                    pNodeId: tempNode.nodeId
                },
                {
                    title: 'label.condition',
                    name: 'label.conditionTip',
                    nodeId: TreeUtil.getTreeId(),
                    type: NodeTypeEnum.conditionItem,
                    pNodeId: tempNode.nodeId
                }
            ]
            tempNode.conditionNode = [...condition];
        } else if (currentNode.child) {
            tempNode.child = currentNode.child;
        }
        tempNode.type = type;
        tempNode.name = 'label.selectedHandleTip';
        tempNode.title = `label.${type}`;
        tempNode.pNodeId = currentNode.nodeId;
        currentNode.child = tempNode;
        this.activeId = tempNode.nodeId
        console.log(this.nodeInfo);
    }
    
    private initData() {
        this.nodeInfo = {
            approved: "",
            name: 'label.startWithOrg',
            title: 'label.startWith',
            type: NodeTypeEnum.start,
            nodeId: TreeUtil.getTreeId()
        }
    }
    
    /**
     * 点击节点
     * @param nodeId
     * @param type
     */
    private clickNode(nodeId: string, type: NodeTypeEnum) {
        this.activeId = nodeId;
        const selectedNode = _.cloneDeep(TreeUtil.findNodeByProperties(this.nodeInfo, nodeId));
        // 不传子节点信息 避免数据太大
        delete selectedNode.child;
        switch (type) {
            case NodeTypeEnum.conditionItem:
                this.currentCondition = selectedNode;
                this.showCondition = true;
                break;
            // 审批和处理同一类型
            case NodeTypeEnum.approve:
            case NodeTypeEnum.cc:
            case NodeTypeEnum.handler:
                this.nodeOperaState = true;
                this.currentNodeInfo = selectedNode;
                break;
            default:
                break;
        }
    }
    
    /**
     * 保存条件
     */
    private onSaveCondition(condition: NodeModel) {
        this.showCondition = false;
        const curNode = TreeUtil.findNodeByProperties(this.nodeInfo, condition.nodeId);
        condition.child = curNode.child;
        Object.assign(curNode, condition);
        this.currentCondition = new NodeModel();
        this.activeId = '';
    }
    
    /**
     * 节点设置保存
     */
    private onSaveNodeInfo(nodeInfo: NodeModel) {
        this.nodeOperaState = false;
        const updateNode = TreeUtil.findNodeByProperties(this.nodeInfo, nodeInfo.nodeId);
        if (updateNode.child) {
            nodeInfo.child = updateNode.child;
        }
        Object.assign(updateNode, nodeInfo);
        this.currentNodeInfo = new NodeModel();
        this.activeId = '';
    }
    
    /**
     * 通知设置保存
     * @param workflowData
     * @private
     */
    private onSaveNoticeConfig(workflowData: WorkflowModel) {
        this.workflowData = workflowData;
        this.noticeSettingState = false;
    }
    
    get collapse() {
        return this.$store.getters[SettingsGetterEnum.collapse]
    }
}
</script>

<style scoped lang="scss">
@import "./css/workflow-csss.scss";

.workflow-container {
    min-height: calc(#{$base-keep-alive-height} - 40px);
    max-height: calc(#{$base-keep-alive-height} - 40px);
    background-color: $workflow-background-color;
    overflow: scroll;
    position: relative;
    
    .opera-top {
        position: fixed;
        top: calc(#{$base-nav-height} + #{$base-tabs-height} + #{$base-padding} * 2);
        z-index: 3;
    }
    
    .workflow-operation-btn-container {
        @extend .opera-top;
        right: calc(#{$base-padding} * 2);
        
        .workflow-operation-btn {
            width: 90px;
            height: 36px;
        }
    }
    
    .workflow-zoom {
        @extend .opera-top;
        left: calc(#{$base-left-menu-width} + 40px);
        line-height: 40px;
        display: inline-flex;
        
        .current-zoom {
            display: inline-block;
            margin: 0 15px;
        }
        
        .zoom-btn {
            margin-top: 5px;
            width: 30px;
            height: 30px;
            border: 1px solid $line-color;
            text-align: center;
            line-height: 30px;
            border-radius: 5px;
            background-color: #fff;
            font-weight: bold;
            cursor: pointer;
        }
        
        &.close {
            left: calc(#{$base-left-menu-width-min} + 40px);
        }
    }
    
    .workflow-content {
        min-height: calc(#{$base-keep-alive-height} - 80px);
        display: inline-flex;
        flex-direction: column;
        justify-content: flex-start;
        align-items: center;
        min-width: 100%;
        padding: 40px 0;
        
        .node-container {
            min-width: 100%;;
            
            .start-container {
                display: inline-flex;
                flex-flow: column;
                justify-content: center;
                align-items: center;
                width: 100%;
                position: relative;
                margin-bottom: 36px;
                
                .start-node {
                    display: block;
                    width: 105px;
                    height: 40px;
                    text-align: center;
                    line-height: 40px;
                    background: #fff;
                    border: 1px solid #e4e7ee;
                    border-radius: 10px;
                }
                
                &:after {
                    content: " ";
                    position: absolute;
                    height: 36px;
                    width: 2px;
                    background-color: $line-color;
                    bottom: -36px;
                    left: 50%;
                }
            }
            
            
            .end-node {
                .end-node-point {
                    width: 20px;
                    height: 20px;
                    margin: auto;
                    border-radius: 50%;
                    background: #fff;
                    border: 2px solid #3f9cfb;
                }
                
                .end-node-text {
                    margin-top: 5px;
                    text-align: center;
                }
            }
        }
    }
}

</style>
